﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace UFODefense
{
    class Laser : DrawableGameComponent
    {
        //UFOCollisionObserver m_UFOobserver;
        double m_creationTime;
        bool m_timeSet;
        SpriteBatch m_spriteBatch;
        ContentManager m_contentManager;
        Color m_color;
        Random m_randomizer;
        Texture2D m_texture;
        Vector2 m_target;
        Vector2 m_actualTarget;
        Vector2 m_gun;

        public Laser(Game game, SpriteBatch SB, ContentManager CM, Random randomizer, float Xpos, Vector2 target)
            : base(game)
        {
            m_spriteBatch = SB;
            m_contentManager = CM;
            m_randomizer = randomizer;
            m_target = target;
            m_gun = new Vector2(Xpos, Definitions.GUN_TIP_Y);

            Game.Components.Add(this);

        }

        public override void Initialize()
        {
            m_timeSet = false;

            RandomizeColor();
            CalculateActualTarget();

            base.Initialize();
        }

        protected override void LoadContent()
        {
            m_texture = m_contentManager.Load<Texture2D>("GFX/laserTexture");
            base.LoadContent();
        }

        public override void Update(GameTime gameTime)
        {
            //set the creation time on the first update
            if (!m_timeSet)
            {
                m_creationTime = gameTime.TotalGameTime.TotalMilliseconds;
                m_timeSet = true;
            }
            //if the laser has lived it's lifetime
            if (gameTime.TotalGameTime.TotalMilliseconds - m_creationTime > Definitions.LASER_LIFETIME)
            {
                Enabled = false;
                Visible = false;
            }
            //Call the collision observer with the lasers information
            UFOCollisionObserver.Instance.Notify(m_gun, m_actualTarget);

            base.Update(gameTime);
        }


        public override void Draw(GameTime gameTime)
        {
            //void DrawLine(SpriteBatch batch, Texture2D blank,
             // float width, Color color, Vector2 point1, Vector2 point2

            float angle = (float)Math.Atan2(m_actualTarget.Y - m_gun.Y, m_actualTarget.X - m_gun.X);
            float length = Vector2.Distance(m_gun, m_actualTarget);
 
            m_spriteBatch.Draw(m_texture, m_gun, null, m_color,
              angle, Vector2.Zero, new Vector2(length, 2.0f),
              SpriteEffects.None, 0);

            base.Draw(gameTime);
        }


        private void RandomizeColor()
        {
            int index = m_randomizer.Next(1, 5);
            switch (index)
            {
                case 1:
                    m_color = Color.Red;
                    return;
                case 2:
                    m_color = Color.Yellow;
                    return;
                case 3:
                    m_color = Color.Blue;
                    return;
                case 4:
                    m_color = Color.Orange;
                    return;
                case 5:
                    m_color = Color.Purple;
                    return;
                default:
                    m_color = Color.Red;
                    return;
            }

        }

        private void CalculateActualTarget()
        {
            float Ydelta = m_target.Y - m_gun.Y;
            float Xdelta = m_target.X - m_gun.X;

            float angularFactor = Ydelta / Xdelta;

            //shot goes left from the gun
            if (Xdelta < 0)
            {
                //we hit the left side of the screen
                if (Math.Abs(angularFactor) * m_gun.X < Definitions.FROM_GUN_TO_TOP)
                {
                    m_actualTarget.X = 0;
                    //the Y-coordinate is the total height minus ground-height (SCREEN_MAX_Y - GUN Y) minus the calculated laserheight
                    m_actualTarget.Y = Definitions.SCREEN_MAX_Y - (Definitions.SCREEN_MAX_Y - m_gun.Y)
                        - (Math.Abs(angularFactor) * m_gun.X);
                }

                //we hit the top of the screen
                else
                {
                    float reverseAngularFactor = Xdelta / Ydelta;
                    m_actualTarget.Y = 0;

                    float shotXtravelDistance = Math.Abs(reverseAngularFactor) * Definitions.FROM_GUN_TO_TOP;
                    //shot goes left from the gun
                    m_actualTarget.X = Definitions.GUN_X - shotXtravelDistance;
                }
            }
            //shot goes right from the gun  
            else
            {
                //we hit the right side of the screen
                if (Math.Abs(angularFactor) * (Definitions.SCREEN_MAX_X - m_gun.X) < Definitions.FROM_GUN_TO_TOP)
                {
                    m_actualTarget.X = Definitions.SCREEN_MAX_X;
                    //the Y-coordinate is the total height minus ground-height (SCREEN_MAX_Y - GUN Y) minus the calculated laserheight
                    m_actualTarget.Y = Definitions.SCREEN_MAX_Y - (Definitions.SCREEN_MAX_Y - m_gun.Y)
                        - (Math.Abs(angularFactor) * (Definitions.SCREEN_MAX_X - m_gun.X));
                }

                //we hit the top of the screen
                else
                {
                    float reverseAngularFactor = Xdelta / Ydelta;
                    m_actualTarget.Y = 0;

                    float shotXtravelDistance = Math.Abs(reverseAngularFactor) * Definitions.FROM_GUN_TO_TOP;
                    m_actualTarget.X = m_gun.X + shotXtravelDistance;
                }
            }           
        }
    }
}
